package com.yima.baseproj.config.responseBody;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yima.baseproj.config.exception.type.ApiException;
import com.yima.baseproj.config.exception.type.ParamException;
import com.yima.baseproj.module.config.utils.ResultCodeE;
import com.yima.baseproj.module.config.utils.ResultUtil;
import com.yima.baseproj.module.config.utils.ResultVo;
import com.yima.baseproj.security.annotation.SecurityIgnoreUrlUtil;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.util.LinkedHashMap;

/**
 * @Author 一码
 * @createDate 2023/4/1 09:00
 * @contact 1424529270@qq.com
 */
@ControllerAdvice()
public class ControllerResponseAdvice implements ResponseBodyAdvice<Object> {

    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        // response是ResultVo类型，或者注释了NotControllerResponseAdvice都不进行包装
        return !(methodParameter.getParameterType().isAssignableFrom(ResultVo.class)
                || methodParameter.hasMethodAnnotation(NotControllerResponseAdvice.class));
    }

    @Override
    public Object beforeBodyWrite(Object data, MethodParameter returnType, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest request, ServerHttpResponse response) {
        if(request.getURI().getPath().startsWith("/server/swagger-resources")
                ||request.getURI().getPath().startsWith("/server/v2/")
                ||request.getURI().getPath().startsWith("/server/doc.html")
                ||request.getURI().getPath().startsWith("/server/swagger-ui.html")
        ){
            return data;
        }

        if(!SecurityIgnoreUrlUtil.isNeedResultVo(returnType)){
            return data;
        }

        // String类型不能直接包装
        if (data instanceof String) {
            ObjectMapper objectMapper = new ObjectMapper();
            try {
                // 将数据包装在ResultVo里后转换为json串进行返回
                return objectMapper.writeValueAsString(ResultUtil.success(data));
            } catch (JsonProcessingException e) {
                throw ApiException.getInstance(e.getMessage());
            }
        }else if(data instanceof ParamException){
            return ResultUtil.error(ResultCodeE.PARAMETER_FAIL.getCode(),((ParamException) data).getMessage());
        }else if(data instanceof LinkedHashMap){
            LinkedHashMap linkedHashMap = (LinkedHashMap) data;
            if(linkedHashMap.containsKey("status")){
                return ResultUtil.error(ResultCodeE.SYS_ERROR.getCode(),linkedHashMap.get("error").toString());
            }
        }
        // 否则直接包装成ResultVo返回
        return ResultUtil.success(data);
    }
}
